package com.itemp.wifidirectsend;

import android.app.IntentService;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.WindowManager;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * An {@link IntentService} subclass for handling asynchronous task requests in
 * a service on a separate handler thread.
 * <p>
 * <p>
 * TODO: Customize class - update intent actions, extra parameters and static
 * helper methods.
 */
public class WifiServerService extends IntentService {
    private static final String TAG = "WifiServerService";
    private static final String WIFI_CONFIG_FILE= "WiFiConfig";
    private static final int PORT = 4786;
    private OnProgressChangListener progressChangListener;
    private MyBinder myBinder = new MyBinder();
    private ServerSocket serverSocket;
    private InputStream inputStream;
    private ObjectInputStream objectInputStream;
    private FileOutputStream fileOutputStream;
    private ProgressDialog progressDialog;
    private FileTransfer fileTransfer;
    private WifiManagerUtils wifiManagerUtils;

    public void setOnProgressChangListener(OnProgressChangListener onProgressChangListener) {
        this.progressChangListener = onProgressChangListener;
    }


    // TODO: Rename actions, choose action names that describe tasks that this
    // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
    private static final String ACTION_FOO = "com.itemp.wifidirectsend.action.FOO";
    private static final String ACTION_BAZ = "com.itemp.wifidirectsend.action.BAZ";

    // TODO: Rename parameters
    private static final String EXTRA_PARAM1 = "com.itemp.wifidirectsend.extra.PARAM1";
    private static final String EXTRA_PARAM2 = "com.itemp.wifidirectsend.extra.PARAM2";

    public WifiServerService() {
        super("WifiServerService");
    }

    class MyBinder extends Binder {
        public WifiServerService getWifiServerService() {
            return WifiServerService.this;
        }
    }

    /**
     * Starts this service to perform action Foo with the given parameters. If
     * the service is already performing a task this action will be queued.
     *
     * @see IntentService
     */
    // TODO: Customize helper method
    public static void startActionFoo(Context context, String param1, String param2) {
        Intent intent = new Intent(context, WifiServerService.class);
        intent.setAction(ACTION_FOO);
        intent.putExtra(EXTRA_PARAM1, param1);
        intent.putExtra(EXTRA_PARAM2, param2);
        context.startService(intent);
    }

    /**
     * Starts this service to perform action Baz with the given parameters. If
     * the service is already performing a task this action will be queued.
     *
     * @see IntentService
     */
    // TODO: Customize helper method
    public static void startActionBaz(Context context, String param1, String param2) {
        Intent intent = new Intent(context, WifiServerService.class);
        intent.setAction(ACTION_BAZ);
        intent.putExtra(EXTRA_PARAM1, param1);
        intent.putExtra(EXTRA_PARAM2, param2);
        context.startService(intent);
    }


    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_FOO.equals(action)) {
                final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                handleActionFoo(param1, param2);
            } else if (ACTION_BAZ.equals(action)) {
                final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                handleActionBaz(param1, param2);
            }
            File file = null;
            try {
                serverSocket = new ServerSocket();
                serverSocket.setReuseAddress(true);
                serverSocket.bind(new InetSocketAddress(PORT));
                Log.e(TAG, "等待客户端连接...");
                Socket client = serverSocket.accept();
                Log.e(TAG, "客户端IP地址 : " + client.getInetAddress().getHostAddress());
                inputStream = client.getInputStream();
                objectInputStream = new ObjectInputStream(inputStream);
                fileTransfer = (FileTransfer) objectInputStream.readObject();
                Log.e(TAG, "待接收的文件: " + fileTransfer);
                String name = new File(fileTransfer.getFilePath()).getName();
                File p2pDirector = new File(Environment.getExternalStorageDirectory() + "/DirectReceiver");
                if (!p2pDirector.exists()){
                    p2pDirector.mkdirs();
                }
                //将文件存储至指定位置
                file = new File(p2pDirector + "/" + name);

                fileOutputStream = new FileOutputStream(file);
                byte buf[] = new byte[512];
                int len;
                long total = 0;
                int progress;
                mHandler.sendEmptyMessage(0);
                while ((len = inputStream.read(buf)) != -1) {
                    fileOutputStream.write(buf, 0, len);
                    total += len;
                    progress = (int) ((total * 100) / fileTransfer.getFileLength());
//                    Log.e(TAG, "文件接收进度: " + progress);
//                    if (progressChangListener != null) {
//                        progressChangListener.onProgressChanged(fileTransfer, progress);
//                    }
                    Message message = new Message();
                    message.what = 1;
                    message.arg1 = progress;
                    mHandler.sendMessage(message);
                }
                mHandler.sendEmptyMessage(2);

                if(WIFI_CONFIG_FILE.equals(name)){
                    String wifiConfig = readExternal(file.getAbsolutePath());
                    Log.d(TAG, "wifiConfig = " + wifiConfig);
                    if (!TextUtils.isEmpty(wifiConfig)) {
                        String[] tempArr = wifiConfig.split(";");
                        for (String string : tempArr) {
                            Log.d(TAG, string);
                        }
                        if (tempArr.length > 1 ) {
                            connectDefaultWifi(tempArr[0], tempArr[1]);
                        }
                    }
                }

                Log.e(TAG, "文件接收成功，文件的MD5码是：" + Md5Util.getMd5(file));
            } catch (Exception e) {
                Log.e(TAG, "文件接收 Exception: " + e.getMessage());
            } finally {
                try {
                    if (serverSocket != null) serverSocket.close();
                    if (inputStream != null) inputStream.close();
                    if (objectInputStream != null) objectInputStream.close();
                    if (fileOutputStream != null) fileOutputStream.close();
                } catch (Exception e) {

                }
                serverSocket = null;
                inputStream = null;
                objectInputStream = null;
                fileOutputStream = null;
                startService(new Intent(this, WifiServerService.class));
            }
        }
    }

    private String readExternal(String filePathName){
        StringBuffer stringBuffer = new StringBuffer();
        String storageState = Environment.getExternalStorageState();
        if (storageState.equals(Environment.MEDIA_MOUNTED)) {
            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(filePathName);
                BufferedInputStream bis = new BufferedInputStream(fileInputStream,5000000);
                byte[] buffer = new byte[1024];
                int len = 0;
                len = bis.read(buffer);
                while (len > 0) {
				stringBuffer.append(new String(buffer, 0, len));
                    len = bis.read(buffer);
                }
                fileInputStream.close();
                bis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return stringBuffer.toString();
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0:
                    showProgressDialog();
                    break;
                case 1:
                    progressDialog.setProgress(msg.arg1);
                    break;
                case 2:
                    if (progressDialog != null && progressDialog.isShowing()) {
                        progressDialog.dismiss();
                        progressDialog = null;
                    }
                    break;
            }
        }
    };

    private void showProgressDialog() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog = null;
        }
        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("Receiving file:" + new File(fileTransfer.getFilePath()).getName());
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//        progressDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        progressDialog.setCancelable(false);
        progressDialog.setCanceledOnTouchOutside(false);
        progressDialog.setMax(100);
        progressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
        progressDialog.show();
    }

    /**
     * Handle action Foo in the provided background thread with the provided
     * parameters.
     */
    private void handleActionFoo(String param1, String param2) {
        // TODO: Handle action Foo
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private boolean listenForMessages(InputStream instream) {
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        try {
            int bytesRead = -1;
            bytesRead = instream.read(buffer);
            if (bytesRead != -1) {
                String result = "";
                while ((bytesRead == bufferSize) && (buffer[bufferSize - 1] != 0)) {
                    result = result + new String(buffer, 0, bytesRead - 1);
                    bytesRead = instream.read(buffer);
                }
                result = result + new String(buffer, 0, bytesRead - 1);
                String finalResult = result;
                if (!TextUtils.isEmpty(finalResult)) {
                    String[] tempArr = finalResult.split(";");
                    for (String string : tempArr) {
                        Log.d(TAG, string);
                    }
                    if (tempArr.length > 2 ) {
                        connectDefaultWifi(tempArr[1], tempArr[2]);
                        return true;
                    }
                }
                Log.d(TAG, "P2P Receiver:" + finalResult);
            }
        } catch (IOException e) {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                serverSocket = null;
            }
        }
        return false;
    }


    private void connectDefaultWifi(String ssid, String psw) {
        if (TextUtils.isEmpty(ssid) || TextUtils.isEmpty(psw)) {
            return;
        }
        wifiManagerUtils = new WifiManagerUtils(this);
        if (wifiManagerUtils.checkWifiState() != WifiManager.WIFI_STATE_ENABLED) {
            if (wifiManagerUtils.openWifiEnabled()) {
                Log.d("yu", "WIFI_STATE_ENABLED!");
            }
        }
        WifiInfo wifiInfo = wifiManagerUtils.getNetWorkId();
        if (TextUtils.isEmpty(wifiInfo.getSSID())) {
            List<ScanResult> scanResults = wifiManagerUtils.getScanResult();
            for (ScanResult sr : scanResults) {
                if (sr.SSID.equals(ssid)) {
                    connectWifi(sr.SSID, psw);
                    break;
                }
            }
        } else {
            if (!wifiInfo.getSSID().equals(ssid)) {
                wifiManagerUtils.disconnectWifi(wifiInfo.getNetworkId());
                connectWifi(ssid, psw);
            }
        }
    }

    private void connectWifi(String ssid, String psw) {
        boolean result = wifiManagerUtils.addNetWork(wifiManagerUtils.createWifiInfo(ssid, psw, 3));
        if (result) {
            Log.d("yu", ssid + " connected!");
        } else {
            Log.d("yu", "connect failed!");
        }
    }


    /**
     * Handle action Baz in the provided background thread with the provided
     * parameters.
     */
    private void handleActionBaz(String param1, String param2) {
        // TODO: Handle action Baz
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return myBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}